package com.aaa.sercurity;


import com.aaa.exception.OauthResponseExceptionTranslator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.error.WebResponseExceptionTranslator;
import org.springframework.security.oauth2.provider.token.TokenEnhancer;
import org.springframework.security.oauth2.provider.token.TokenEnhancerChain;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.util.ArrayList;
import java.util.List;

@Configuration
@EnableAuthorizationServer
public class OauthConfig extends AuthorizationServerConfigurerAdapter {

    private final String SIGNING_KEY = "book";
    private final String SIGNING_KEY1 = "front";

    @Resource
    PasswordEncoder passwordEncoder;

    @Resource
    UserDetailsConfig userDetailsConfig;
    @Resource
    AuthenticationManager authenticationManager;

    @Resource
    DataSource dataSource;

    @Resource
    JwtEnhanse jwtEnhanse;

    /**
     * token:
     * 保存位置:内存中/redis
     * 生成方式:jwt
     */

    /**
     * jwttoken转换器
     * @return
     */
    @Bean
    public JwtAccessTokenConverter jwtTokenConverter(){
        JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter();
//        System.out.println(jwtAccessTokenConverter.getKey()+"这是我的jwt");
//        if(jwtAccessTokenConverter.toString().equals("vueback")) {
            jwtAccessTokenConverter.setSigningKey(SIGNING_KEY);
            jwtAccessTokenConverter.setVerifierKey(SIGNING_KEY);
            return jwtAccessTokenConverter;
//        }else if(jwtAccessTokenConverter.toString().equals("vuefront")) {
//            jwtAccessTokenConverter.setSigningKey(SIGNING_KEY1);
//            jwtAccessTokenConverter.setVerifierKey(SIGNING_KEY1);
//            return jwtAccessTokenConverter;
//        }else{
//            return null;
//        }
    }

    /**
     * token 存储
     * @return
     */
    @Bean
    public TokenStore jwtTokenStore(){
        // new InMemoryTokenStore(); 保存在内存中
        // new RedisTokenStore(); 保存在redis
        return new JwtTokenStore(jwtTokenConverter());
    }

    @Bean
    public WebResponseExceptionTranslator initResponseExceptionTranslator(){
        return new OauthResponseExceptionTranslator();
    }

    /**
     * 密码模式认证管理器
     *
     * @param endpoints
     * @throws Exception
     */
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
        List<TokenEnhancer> list = new ArrayList<>();
        list.add(jwtEnhanse); //jwt的增强器
        list.add(jwtTokenConverter()); //jwt的转换器
        endpoints.authenticationManager(authenticationManager);
        tokenEnhancerChain.setTokenEnhancers(list);
        // token
        endpoints
                //jwt生成
                .tokenStore(jwtTokenStore())
                //增强
                .accessTokenConverter(jwtTokenConverter())
                //存储方式
                .tokenEnhancer(tokenEnhancerChain)
                //更新刷新token
                .userDetailsService(userDetailsConfig)
                .authenticationManager(authenticationManager)
                //异常解析器:解析异常
                .exceptionTranslator(initResponseExceptionTranslator());
    }


    /**
     * 客户端详情配置(第三方应用)
     *
     * authorization_code：授权码类型
     * 1.授权码模式（authorization_code）
     * 2.简化模式（implicit）
     * 3.密码模式（resource owner password credentials）
     * 4.客户端模式（client_credentials）
     * 5.通过以上授权获得的刷新令牌来获取新的令牌（refresh_token）
     *
     * @param clients
     * @throws Exception
     */
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        // 从数据库中加载客户端详细信息：oauth_client_details
        clients.jdbc(dataSource).passwordEncoder(passwordEncoder);
    }

    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {

        security.passwordEncoder(passwordEncoder);
        // 允许使用表单进行客户端认证
        security.allowFormAuthenticationForClients();
        /**
         * POST /oauth/authorize  授权码模式认证授权接口
         * GET/POST /oauth/token  获取 token 的接口
         * POST  /oauth/check_token  检查 token合法性接口
         */
        // oauth2中，获取token，验证token接口不需要认证
        security.tokenKeyAccess("permitAll");
        security.checkTokenAccess("permitAll");
    }


}
